package com.ibm.cloud.banking.trans.customer;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibm.cloud.banking.facade.account.IAccountFacade;
import com.ibm.cloud.banking.facade.customer.ICustomerCommandFacade;
import com.ibm.cloud.banking.facade.customer.dto.CreateCustomerDTO;
import com.ibm.cloud.banking.facade.customer.dto.CustomerCertificateDTO;
import com.ibm.cloud.banking.facade.customer.dto.QueryCustomerRespDTO;
import com.ibm.cloud.banking.trans.customer.dto.Req102001;
import com.ibm.cloud.banking.trans.customer.dto.Resp102001;
import org.apache.camel.Exchange;
import org.apache.camel.Expression;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spi.Synchronization;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class Trans102001 extends RouteBuilder {

    @Resource
    IAccountFacade accountFacade;

    @Resource
    ICustomerCommandFacade customerCommandFacade;

    final ObjectMapper mapper = new ObjectMapper();

    String PCS_CODE = "T18";
    String ROUTE_URI = "direct:T18";
    String ROUTE_DESC = "新建客户交易";
    String ROUTE_ID = "PCS-FLOW-T18";

    private final String ORIGINAL_REQUEST_BODY_KEY = "ORIGINAL-REQUEST-BODY";

    private final String CHECK_CUSTOMER_EXIST = "direct:400";
    private final String SAVE_CUSTOMER_CERTIFICATE = "direct:401";
    private final String SAVE_CUSTOMER = "direct:402";
    private final String GET_CUSTOMER = "direct:403";

    @Override
    public void configure() throws Exception {

        from(ROUTE_URI)
                .routeDescription(ROUTE_DESC)
                .routeId(ROUTE_ID)
                .log("开始执行新开客户交易。")
                .to(CHECK_CUSTOMER_EXIST)
                .to(SAVE_CUSTOMER_CERTIFICATE)
//                .saga()
//                .timeout(1, TimeUnit.MINUTES)
//                .propagation(SagaPropagation.REQUIRES_NEW)  //使用 exchange 的同步补偿
                .to(SAVE_CUSTOMER)
                .to(GET_CUSTOMER)
                .log("新开客户交易执行结束");


        // 根据客户三要素，查询客户证件信息，如果客户证件信息不存在，交易继续执行，
        // 否则抛出：该证件已经存在，客户号为【客户编号】
        from(CHECK_CUSTOMER_EXIST)
                .process(exchange -> {
                    // exchange.getIn().getBody(Req102001.class) is null
                    //Req102001 request  = exchange.getIn().getBody(Req102001.class);
                    Map<String, Object> requestMsg = (LinkedHashMap<String, Object>)exchange.getIn().getBody();
                    //// 缓存源始请求报文体
                    exchange.setProperty(ORIGINAL_REQUEST_BODY_KEY,mapper.readValue(mapper.writeValueAsString(requestMsg),Req102001.class));

                    CustomerCertificateDTO certificateDTO = new CustomerCertificateDTO();
                    certificateDTO.setIdNo((String)requestMsg.get("idNo"));
                    certificateDTO.setIdType((String)requestMsg.get("idType"));
                    certificateDTO.setName((String)requestMsg.get("name"));

                    exchange.getIn().setBody(certificateDTO, CustomerCertificateDTO.class);
                })
                .bean(customerCommandFacade, "isExist").log("检查客户证件是否已存在");

        // 客户证件信息不存在，保存客户证件信息，生成客户号、新定位目标单元
        from(SAVE_CUSTOMER_CERTIFICATE)
                .process(exchange -> {
                    Req102001 requestMsg = (Req102001)exchange.getProperty(ORIGINAL_REQUEST_BODY_KEY);
                    CustomerCertificateDTO certificateDTO = new CustomerCertificateDTO();
                    certificateDTO.setIdNo(requestMsg.getIdNo());
                    certificateDTO.setIdType(requestMsg.getIdType());
                    certificateDTO.setName(requestMsg.getName());
                    certificateDTO.setCustomerNo(requestMsg.getCustomerNo());
                    exchange.getIn().setBody(certificateDTO, CustomerCertificateDTO.class);
                    exchange.getUnitOfWork().addSynchronization(new Synchronization() {
                        @Override
                        public void onComplete(Exchange exchange) {

                        }

                        @Override
                        public void onFailure(Exchange exchange) {
                            customerCommandFacade.deleteCustomerCertificate(certificateDTO);
                        }
                    });
                })
                .bean(customerCommandFacade, "saveCustomerCertificate").log("客户领域-生成客户编号并保存证件信息");

        // 创建客户信息
        from(SAVE_CUSTOMER)
                .process(exchange -> {
                    Req102001 requestMsg = (Req102001)exchange.getProperty(ORIGINAL_REQUEST_BODY_KEY);
                    CreateCustomerDTO customerDTO = new CreateCustomerDTO();
                    BeanUtils.copyProperties(requestMsg, customerDTO);
                    exchange.getIn().setBody(customerDTO, CreateCustomerDTO.class);
                    exchange.getUnitOfWork().addSynchronization(new Synchronization() {
                        @Override
                        public void onComplete(Exchange exchange) {

                        }

                        @Override
                        public void onFailure(Exchange exchange) {
                            customerCommandFacade.deleteCustomer(requestMsg.getIdType(),
                                    requestMsg.getIdNo(),requestMsg.getName());
                        }
                    });
                })
                .bean(customerCommandFacade, "addNewCustomer").log("创建新客户信息");

        from(GET_CUSTOMER)
                .process(exchange -> {
                    Req102001 requestMsg = (Req102001)exchange.getProperty(ORIGINAL_REQUEST_BODY_KEY);
                    exchange.getIn().setBody(requestMsg.getCustomerNo(), String.class);
                })
                .bean(customerCommandFacade, "getCustomerByNo")
                .process(exchange -> {
                    QueryCustomerRespDTO customerDto = exchange.getIn().getBody(QueryCustomerRespDTO.class);
                    Resp102001 response = new Resp102001();
                    BeanUtils.copyProperties(customerDto, response);
                    exchange.getIn().setBody(response, Req102001.class);
                }).log("查询新建客户信息");

    }
}